from odoo import api, models, fields, _
from odoo.exceptions import ValidationError
from odoo.tools import float_compare
from collections import defaultdict


class SupplierinfoWizard(models.Model):
    _name = 'supplierinfo.wizard'

    apply_id = fields.Many2one('sb.subcontracting.apply')
    product_id = fields.Many2one('product.product', string='Product')
    product_ids = fields.Many2many('product.product', 'supplierinfo_wizard_product_rel', 'supplierinfo_wizard_id',
                                   'product_id', string='Products')
    supplierinfo_id = fields.Many2one('subcontract.product.supplierinfo', string='Vendor')
    service_product_id = fields.Many2one('product.product', 'Sub service')
    service_product_ids = fields.Many2many('product.product', 'supplierinfo_wizard_product_rel02',
                                           'supplierinfo_wizard_id', 'product_id')
    line_ids = fields.One2many('supplierinfo.line.wizard', 'wizard_id', string='Lines')
    is_all = fields.Boolean(default=False, string="All the same")
    partner_id = fields.Many2one('res.partner', string='外发供应商')

    @api.onchange('partner_id')
    def onchange_line_ids(self):
        for line in self.line_ids:
            if self.partner_id:
                domain = [('partner_id', '=', self.partner_id.id),
                          ('service_product_id', '=', line.service_product_id.id),
                          ('product_id', '=', line.product_id.id)]
                supplierinfo = self.env['subcontract.product.supplierinfo'].search(domain, order='write_date desc',
                                                                                   limit=1)
                if supplierinfo and supplierinfo.service_product_id.s_service_pricing_method == 'panel':
                    vals = {'price_unit': supplierinfo.panel_price, 'supplierinfo_id': supplierinfo.id,
                            'partner_id': self.partner_id.id}
                    line.write(vals)
                elif supplierinfo and supplierinfo.service_product_id.s_service_pricing_method == 'area':
                    area_price_unit = supplierinfo.area_price_unit
                    area_pnl_qty = supplierinfo.area_pnl_qty
                    price_unit = round(supplierinfo.area_price_unit * supplierinfo.area_pnl_qty, 4)
                    vals = {'area_price_unit': area_price_unit,
                            'area_pnl_qty': area_pnl_qty,
                            'price_unit': price_unit,
                            'supplierinfo_id': supplierinfo.id,
                            'partner_id': self.partner_id.id}
                    line.write(vals)
                else:
                    vals = {'partner_id': self.partner_id.id, 'supplierinfo_id': False, 'price_unit': 0,
                            'area_price_unit': 0}
                    line.write(vals)
            else:
                line.write({'partner_id': False, 'supplierinfo_id': False, 'price_unit': 0, 'area_price_unit': 0})

    def button_confirm(self):
        for line in self.line_ids:
            if line.service_product_id.s_service_pricing_method == 'panel' and not line.price_unit:
                raise ValidationError(_("外发单价必须大于0"))
            elif line.service_product_id.s_service_pricing_method == 'area' and not line.area_price_unit:
                raise ValidationError(_("平米单价必须大于0"))
            if line.supplierinfo_id:
                self.auto_update_supplierinfo(line)
            else:
                self.auto_create_supplierinfo(line)
            vals = {
                'area_price_unit': line.area_price_unit,
                'area_pnl_qty': line.area_pnl_qty,
                'price_unit': line.price_unit,
                'supplierinfo_id': line.supplierinfo_id.id,
                'partner_id': line.partner_id.id
            }
            line.sub_apply_line_id.write(vals)
        self.create_purchase()
        self.update_purchase()

    def auto_update_supplierinfo(self, line):
        """单价调整更新价格"""
        if line.service_product_id.s_service_pricing_method == 'panel':
            c_price = line.price_unit
            s_price = line.supplierinfo_id.panel_price
            if float_compare(c_price, s_price, precision_rounding=0.001):
                """更新价格表"""
                line.supplierinfo_id.panel_price = c_price
            else:
                pass
        elif line.service_product_id.s_service_pricing_method == 'area':
            c_price = line.area_price_unit
            s_price = line.supplierinfo_id.area_price_unit
            if float_compare(c_price, s_price, precision_rounding=0.001):
                """更新价格表"""
                line.supplierinfo_id.area_price_unit = c_price
            else:
                pass

    def auto_create_supplierinfo(self, line):
        """没有价格表自动创建"""
        vals = {}
        if line.service_product_id.s_service_pricing_method == 'panel':
            vals = {
                'partner_id': line.partner_id.id,
                'name': line.partner_id.complete_name,
                'service_product_id': line.service_product_id.id,
                'panel_price': line.price_unit
            }

        elif line.service_product_id.s_service_pricing_method == 'area':
            vals = {
                'partner_id': line.partner_id.id,
                'service_product_id': line.service_product_id.id,
                'name': line.partner_id.complete_name,
                'area_price_unit': line.area_price_unit,
                'area_pnl_qty': line.area_pnl_qty
            }
        if vals:
            supplierinfo = self.env['subcontract.product.supplierinfo'].create(vals)
            line.supplierinfo_id = supplierinfo

    def _get_product_specs(self, product_id, compute_type):
        uom_values = {x.uom_id.code: x.uom_value for x in product_id.uom_value_ids}
        if compute_type == 'set':
            w = uom_values.get('SETW', 1)
            h = uom_values.get('SETL', 1)
            result = f"SET:{str(h)};\nSET宽{str(w)}"
        else:
            w = uom_values.get('PNLW', 1)
            h = uom_values.get('PNLL', 1)
            result = f"PNL长:{str(h)};\nPNL宽{str(w)}"
        return result

    def create_purchase(self):
        partners = {}
        # 'apply_id': purchase_vals
        app_pur = defaultdict(list)
        purchase_vals = []
        uom_set = self.env.ref('pcbmanufact.uom_set')
        uom_panel = self.env.ref('pcbmanufact.uom_panel')
        for line in self.line_ids:
            if line.area_calculation_method == 'set':
                uom = uom_set
            else:
                uom = uom_panel
            specs = self._get_product_specs(line.product_id, line.area_calculation_method)
            ex_poid = partners.get(line.partner_id.id) or 0
            apply_id = line.sub_apply_line_id.apply_id
            if not ex_poid:
                values = {
                    'partner_id': line.partner_id.id,
                    'subcontracting': True,
                    'sb_subcontracting_apply_id': self.apply_id.id,
                    's_service_pricing_method': line.supplierinfo_id.s_service_pricing_method,
                    'order_line': [(0, 0, {
                        'product_id': line.service_product_id.id if not self.apply_id.is_all_outside else self.product_id.id,
                        'name': line.remark,
                        'product_uom': uom.id,
                        'display_type': False,
                        'date_planned': fields.Datetime.now(),
                        'workorder_id': line.sub_apply_line_id.workorder_id.id,
                        's_subcontracting_product_id': line.product_id.id,
                        's_production_id': line.sub_apply_line_id.production_id.id,
                        's_specs': specs,
                        'qty_wip_pcs': line.sub_apply_line_id.qty_wip,  # pcs数
                        'area_pnl_qty': line.area_pnl_qty,  # 单pnl 有效面积
                        'area_price_unit': line.area_price_unit,  # 每平米单价
                        's_area': line.area,  # 总平米数
                        'price_unit': line.price_unit,
                        'product_qty': line.qty,  # PNL 数
                        'sb_subcontracting_apply_line_id': line.sub_apply_line_id.id,
                        'taxes_id': [(4, line.supplier_taxes_id.id)] if line.supplier_taxes_id else None,  # PNL 数
                        # 'remark': remarks
                    })]
                }
                poid = self.env['purchase.order'].create(values)
                # line.done = True
                line.sub_apply_line_id.purchase_order_id = poid.id
                partners[line.partner_id.id] = poid.id
                purchase_vals.append((4, poid.id))
                app_pur[apply_id].append((4, poid.id))
            else:
                self.env['purchase.order.line'].create({
                    'order_id': ex_poid,
                    'product_id': line.service_product_id.id if not self.apply_id.is_all_outside else self.product_id.id,
                    'name': line.remark,
                    'product_uom': uom.id,
                    'display_type': False,
                    'date_planned': fields.Datetime.now(),
                    'workorder_id': line.sub_apply_line_id.workorder_id.id,
                    's_subcontracting_product_id': line.product_id.id,
                    's_production_id': line.sub_apply_line_id.production_id.id,
                    's_specs': specs,
                    'qty_wip_pcs': line.sub_apply_line_id.qty_wip,  # pcs数
                    'area_pnl_qty': line.area_pnl_qty,  # 单pnl 有效面积
                    'area_price_unit': line.area_price_unit,  # 每平米单价
                    's_area': line.area,  # 总平米数
                    'price_unit': line.price_unit,
                    'product_qty': line.qty,  # PNL 数
                    'sb_subcontracting_apply_line_id': line.sub_apply_line_id.id,
                    'taxes_id': [(4, line.supplier_taxes_id.id)] if line.supplier_taxes_id else None,  # PNL 数
                    # 'remark': remarks
                })
                # line.done = True
                line.sub_apply_line_id.purchase_order_id = ex_poid
        for k, v in app_pur.items():
            k.purchase_order_ids = v
        # self.apply_id.purchase_order_ids = purchase_vals

        tree_id = self.env.ref('purchase.purchase_order_kpis_tree').id
        form_id = self.env.ref('purchase.purchase_order_form').id
        po_ids = [p[1] for p in purchase_vals]
        return {
            'name': 'Rework',
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form, tree',
            'res_model': 'purchase.order',
            'domain': [('id', 'in', po_ids)],
            'views': [(tree_id, 'tree'), (form_id, 'form')],
            'context': {'create': 0},
        }

    def update_purchase(self):
        for p in self.apply_id.purchase_order_ids:
            if self.apply_id.is_all_outside:
                p.s_service_pricing_method = 'panel'
            else:
                mth = []
                for l in p.order_line:
                    mth.append(l.product_id.s_service_pricing_method)
                if 'panel' in mth:
                    p.s_service_pricing_method = 'panel'
                else:
                    p.s_service_pricing_method = 'area'

    def get_unit_number(self, product_id):
        uom_panel_width = self.env.ref('pcbmanufact.uom_panel_width')
        uom_panel_length = self.env.ref('pcbmanufact.uom_panel_length')
        uom_ids = product_id.uom_value_ids.mapped('uom_id')
        pnl_width = 0
        pnl_length = 0
        if uom_panel_width in uom_ids and uom_panel_length in uom_ids:
            pnl_width = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == uom_panel_width.id).uom_value
            pnl_length = product_id.uom_value_ids.filtered(lambda x: x.uom_id.id == uom_panel_length.id).uom_value
        return pnl_length, pnl_width

    def create_supplierinfo(self):
        context = dict(self._context)
        pnl_length, panel_width = self.get_unit_number(self.product_id)
        area_pnl_qty = round(pnl_length * panel_width / 1000000, 3)
        context['default_product_id'] = self.product_id.id
        context['default_area_pnl_qty'] = area_pnl_qty
        context['default_service_product_id'] = self.service_product_id.id
        form_id = self.env.ref("sb_subcontracting.subcontract_product_supplierinfo_form_view").id
        return {
            'name': 'Create Supplierinfo',
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form',
            'target': 'new',
            'res_model': 'subcontract.product.supplierinfo',
            'views': [(form_id, 'form')],
            'context': context,
        }


class SupplierinfoLineWizard(models.Model):
    _name = 'supplierinfo.line.wizard'

    wizard_id = fields.Many2one('supplierinfo.wizard')
    supplierinfo_id = fields.Many2one('subcontract.product.supplierinfo', string='Vendor')
    area_price_unit = fields.Float('Area Price Unit', digits="Product Unit of Measure")
    area_pnl_qty = fields.Float(string='Active PANEL/M²', digits="Product Unit of Measure")
    supplier_taxes_id = fields.Many2one(comodel_name='account.tax', string="Taxes")
    area = fields.Char(string='Area', copy=False)
    qty = fields.Float('Quantity for This Order', digits='Product Unit of Measure')
    remark = fields.Text(string='description')
    service_product_id = fields.Many2one('product.product')
    sub_apply_line_id = fields.Many2one('sb.subcontracting.apply.line')
    product_id = fields.Many2one('product.product', string='Product')
    price_unit = fields.Float('Price Unit', digits="Product Unit of Measure")
    partner_id = fields.Many2one('res.partner', string='supplier')

    area_calculation_method = fields.Selection([
        ('pnl', 'PNL'),
        ('set', 'SET')
    ], string='Area calculation method')

    @api.onchange('partner_id')
    def onchange_price(self):
        if self.partner_id:
            domain = [
                ('partner_id', '=', self.partner_id.id),
                ('service_product_id', '=', self.service_product_id.id),
                ('product_id', '=', self.product_id.id)
            ]
            supplierinfo = self.env['subcontract.product.supplierinfo'].search(domain, order='write_date desc', limit=1)
            if supplierinfo and supplierinfo.service_product_id.s_service_pricing_method == 'panel':
                vals = {'price_unit': supplierinfo.panel_price, 'supplierinfo_id': supplierinfo.id}
                self.write(vals)
            elif supplierinfo and supplierinfo.service_product_id.s_service_pricing_method == 'area':
                area_price_unit = supplierinfo.area_price_unit
                area_pnl_qty = supplierinfo.area_pnl_qty
                price_unit = round(supplierinfo.area_price_unit * supplierinfo.area_pnl_qty, 4)
                vals = {
                    'area_price_unit': area_price_unit,
                    'area_pnl_qty': area_pnl_qty,
                    'price_unit': price_unit,
                    'supplierinfo_id': supplierinfo.id
                }
                self.write(vals)
            else:
                vals = {
                    'supplierinfo_id': False,
                    'price_unit': 0,
                    'area_price_unit': 0
                }
                self.write(vals)
            vals['partner_id'] = self.partner_id.id
        else:
            vals = {
                'supplierinfo_id': False,
                'price_unit': 0,
                'area_price_unit': 0,
                'partner_id': False
            }
            self.write(vals)

    @api.onchange('area_price_unit', 'area_pnl_qty')
    def onchange_area_price(self):
        if self.service_product_id.s_service_pricing_method == 'area':
            self.price_unit = round(self.area_price_unit * self.area_pnl_qty, 4)
